# -*- coding: utf-8 -*-
# Gestión interna de clases.

## vipera, un diseñador de aplicaciones para Python
##     Copyright (C) 2011 Ángel Luis García García
##
##    This program is free software: you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation, either version 3 of the License, or
##    (at your option) any later version.
##
##    This program is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with this program.  If not, see <http://www.gnu.org/licenses/>.

class modelo_texto_ogl(object):
    '''Gestión de mensajes de texto'''
    def __init__(self):
        '''Constructor de clase'''
        self.__lista_textos = list()

    def textos(self):
        '''Devuelve lista de textos'''
        return self.__lista_textos
        
    def eliminar_todo(self):
        '''Elimina todos los textos'''
        for i in self.__lista_textos:
            i[1].Delete()
            self.__lista_textos.remove(i)
        self.__lista_textos = list()
        
    def add_texto(self, texto, shape):
        '''Añade un texto'''
        if texto is None: return False
        if len(unicode(texto).strip()) == 0: return False
        # if not isinstance(shape, ogl.TextShape)
        self.__lista_textos.append([texto, shape])
        
    def eliminar_texto(self, shape):
        '''Elimina un texto'''
        for i in self.__lista_textos:
            if i[1] == shape:
                i[1].Delete()
                self.__lista_textos.remove(i)
                # print "ELIMINADO"
                print self.__lista_textos
                break
    
    def modificar_texto(self, texto, shape):
        '''Modifica un texto'''
        for i in self.__lista_textos:
            if i[1] == shape:
                i[0] = texto
                break
    
class modelo_clase(object):
    '''Estructura de modelo de datos de clase'''
    # Nombre de clase.
    nombre = None
    # Clases externas de las que hereda.
    clases_externas = None
    # Código extra para el constructor (el __init__).
    # codigo_init = None
    # Código constructor inicial: [código Python, flag de activación de código]
    codigo_constructor_ini = list() # [None, False] 
    # Código constructor final: [código Python, flag de activación de código]
    codigo_constructor_fin = list() # [None, False]
    # Código destructor: [código Python, flag de activación de código]
    codigo_destructor = list() # [None, False]
    # Constantes de clase: [(const1, valor), ..., (constN, valor)]
    constantes = list()
    # Comentario
    comentario = None
    # Lista de parámetros: [(param1, valor_ini), ..., (paramN, valor_ini)]
    parametros = list()
    # Lista de atributos: [(atrib1, valor_ini, oculto), ..., (atribN, valor_ini, oculto)]
    atributos = list()
    # Lista de propiedades: [(prop1, valor_ini, info), ..., (propN, valor_ini, info)]
    propiedades = list()
    # [17-07-2011] Se incluye el elemento "codigo", para guardar el código Python asociado al método.
    # [27-07-2011] Sacamos "oculto" fuera y lo incluimos como característica de método.
    # Lista de métodos: [[metodo1, info, ((param1, valor_ini, tipo_dato), ..., 
    # (paramN, valor_ini, tipo_dato)), codigo, oculto],..., [metodoK, info, (param1, valor_ini, tipo_dato), ..., 
    # (paramJ, valor_ini, tipo_dato)), codigo, oculto]]
    metodos = list()
    
class modelo_clases(object):
    '''Estructura de modelo de clases'''
    def __init__(self):
        '''Constructor de clase'''        
        self.__lista_clases = []
     
    def existe_clase(self, nombre_clase):
        '''Devuelve cierto si la clase nombre_clase existe y falso en caso contrario'''
        for i in self.__lista_clases:
            if i[0].nombre == nombre_clase:
                return True
        return False
        
    def clases(self):
        '''Devuelve la lista de clases'''
        return self.__lista_clases
    
    def ordenar_clases_por_nombre(self, orden):
        '''Ordenación de clases a partir de una lista de orden'''
        aux = []
        for i in orden:
            puntero = -1
            for j in self.__lista_clases:
                puntero += 1
                if i == j[0].nombre:
                    clase = self.__lista_clases.pop(puntero)
                    aux.append(clase)
                    break
        self.__lista_clases = aux
    
    def set_clases(self, lista_clases):
        '''Asigna una nueva lista de clases'''
        self.__lista_clases = lista_clases
        
    def clases_sin_divided_shape(self):
        '''Método que devuelve la estructura sin las referencias a los DividedShape'''
        ret = list()
        for i in self.__lista_clases:
            c = i[0]
            d = None
            ret.append([c, d])
        return ret
            
    def crear_clase(self, nombre_clase, divided_shape):
        '''Creación de una clase'''
        # Instanciamos una estructura de clase, e incluimos el nombre.
        clase = modelo_clase()
        clase.nombre = nombre_clase
        clase.clases_externas = None
        # clase.codigo_init = None
        clase.comentario = None
        clase.parametros = list()
        clase.atributos = list()
        clase.propiedades = list()
        clase.metodos = list()        
        clase.codigo_constructor_ini = ['', False]
        clase.codigo_constructor_fin = ['', False]
        clase.codigo_destructor = ['', False]
        clase.constantes = list()
        # Lo incluimos.
        self.__lista_clases.append([clase, divided_shape])
        
    def eliminar_clase(self, nombre):
        '''Eliminación de una clase'''
        for i in self.__lista_clases:
            if i[0].nombre == nombre:
                self.__lista_clases.remove(i)
                break
         
    def guardar_clases(self):
        '''Guarda la información de las clases'''
        # En este caso, hay que recorrer todos los divided_shape
        # y obtener sus posiciones (X,Y), para poder restaurarlas
        # más tarde.
        #for i in self.__lista_clases:
        pass   
    
    def get_divided_shape(self, nombre):
        '''Devuelve el divided_shape a partir del nombre pasado como parámetro'''
        for i in self.__lista_clases:
            if i[0].nombre.lower() == nombre.lower():
                return i[1]
        return None
                
class modelo_relaciones(object):
    '''Modelo de relación entre clases'''
    def __init__(self):
        '''Constructor de clase'''        
        self.__lista_relaciones = []

    def set_relaciones(self, lista_relaciones):
        '''Asigna nueva lista de relaciones entre clases'''
        self.__lista_relaciones = lista_relaciones
        
    def existe_relacion(self, npadre, nhijo):
        '''Devuelve True si existe la relación y False en caso contrario'''
        for i in self.__lista_relaciones:
            if i[1] == npadre and i[2] == nhijo: return True
        # Nos vamos.
        return False

    def renombrar_relacion(self, old_name, new_name):
        '''Renombra una clase en el sistema de relaciones'''
        # Buscamos en todas las relaciones..
        for i in self.__lista_relaciones:
            # Buscamos el nombre antiguo y lo cambiamos por el nuevo.
            if i[1] == old_name: i[1] = new_name
            if i[2] == old_name: i[2] = new_name
            i[0] = "%s <- %s" % (i[1], i[2])
        # Nos vamos.
        return True
    
    def crear_relacion(self, npadre, nhijo, nombre_relacion = None):
        '''Crea una relación a partir del padre e hijo'''
        # Si no se pasa el nombre de la relación, se crea.
        if nombre_relacion is None:
            nombre_relacion = "%s <- %s" % (npadre, nhijo)
        # Comprobamos que no existe la relación.
        if self.existe_relacion(npadre, nhijo): return False
        # Incluimos la nueva relación.
        self.__lista_relaciones.append([nombre_relacion,npadre,nhijo])
        # Nos vamos.
        return True
    
    def eliminar_relacion(self, nombre_relacion):
        '''Elimina una relación'''
        for i in self.__lista_relaciones:
            if i[0] == nombre_relacion: 
                self.__lista_relaciones.remove(i)
                return True
        # Nos vamos.
        return False

    def eliminar_relacion2(self, padre, hijo):
        '''Elimina una relación a partir del padre e hijo'''
        for i in self.__lista_relaciones:
            if i[1] == padre and i[2] == hijo: 
                self.__lista_relaciones.remove(i)
                return True
        # Nos vamos.
        return False
  
    def relaciones(self):
        '''Devuelve la lista de relaciones'''
        return self.__lista_relaciones
 
    def get_padre_hijo(self, relacion):
        '''Devuelve la tupla (padre, hijo) a partir de la relación'''
        for i in self.__lista_relaciones:
            if i[0] == relacion: return i[1], i[2]
        return None, None

class modelo_relaciones_dependencia(object):
    '''Modelo de relación de dependencia entre clases'''
    def __init__(self):
        '''Constructor de clase'''        
        self.__lista_relaciones = list()

    def set_relaciones(self, lista_relaciones):
        '''Asigna nueva lista de relaciones de dependencia entre clases'''
        self.__lista_relaciones = lista_relaciones
        
    def existe_relacion(self, npadre, nhijo):
        '''Devuelve True si existe la relación y False en caso contrario'''
        for i in self.__lista_relaciones:
            if i[0] == npadre and i[1] == nhijo: return True
        # Nos vamos.
        return False
   
    def crear_relacion(self, npadre, nhijo):
        '''Crea una relación a partir del padre e hijo'''
        # Comprobamos que no existe la relación.
        if self.existe_relacion(npadre, nhijo): return False
        # Incluimos la nueva relación.
        self.__lista_relaciones.append([npadre,nhijo])
        # Nos vamos.
        return True
    
    def eliminar_relacion(self, npadre, nhijo):
        '''Elimina una relación'''
        for i in self.__lista_relaciones:
            if i[0] == npadre and i[1] == nhijo: 
                self.__lista_relaciones.remove(i)
                return True
        # Nos vamos.
        return False
 
    def relaciones(self):
        '''Devuelve la lista de relaciones'''
        return self.__lista_relaciones
